/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package dao;

import dao.exceptions.IllegalOrphanException;
import dao.exceptions.NonexistentEntityException;
import dao.exceptions.PreexistingEntityException;
import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import modelo.Profesor;
import modelo.Facultad;
import modelo.Archivos;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import modelo.Califica;
import modelo.EntidadesVinculadas;
import modelo.Proyecto;

/**
 *
 * @author Fabian
 */
public class ProyectoJpaController implements Serializable {

    public ProyectoJpaController(EntityManagerFactory emf) {
        this.emf = emf;
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Proyecto proyecto) throws PreexistingEntityException, Exception {
        if (proyecto.getArchivosList() == null) {
            proyecto.setArchivosList(new ArrayList<Archivos>());
        }
        if (proyecto.getCalificaList() == null) {
            proyecto.setCalificaList(new ArrayList<Califica>());
        }
        if (proyecto.getEntidadesVinculadasList() == null) {
            proyecto.setEntidadesVinculadasList(new ArrayList<EntidadesVinculadas>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Profesor cedulaProfesor = proyecto.getCedulaProfesor();
            if (cedulaProfesor != null) {
                cedulaProfesor = em.getReference(cedulaProfesor.getClass(), cedulaProfesor.getCedula());
                proyecto.setCedulaProfesor(cedulaProfesor);
            }
            Facultad facultad = proyecto.getFacultad();
            if (facultad != null) {
                facultad = em.getReference(facultad.getClass(), facultad.getNombre());
                proyecto.setFacultad(facultad);
            }
            List<Archivos> attachedArchivosList = new ArrayList<Archivos>();
            for (Archivos archivosListArchivosToAttach : proyecto.getArchivosList()) {
                archivosListArchivosToAttach = em.getReference(archivosListArchivosToAttach.getClass(), archivosListArchivosToAttach.getArchivosPK());
                attachedArchivosList.add(archivosListArchivosToAttach);
            }
            proyecto.setArchivosList(attachedArchivosList);
            List<Califica> attachedCalificaList = new ArrayList<Califica>();
            for (Califica calificaListCalificaToAttach : proyecto.getCalificaList()) {
                calificaListCalificaToAttach = em.getReference(calificaListCalificaToAttach.getClass(), calificaListCalificaToAttach.getCalificaPK());
                attachedCalificaList.add(calificaListCalificaToAttach);
            }
            proyecto.setCalificaList(attachedCalificaList);
            List<EntidadesVinculadas> attachedEntidadesVinculadasList = new ArrayList<EntidadesVinculadas>();
            for (EntidadesVinculadas entidadesVinculadasListEntidadesVinculadasToAttach : proyecto.getEntidadesVinculadasList()) {
                entidadesVinculadasListEntidadesVinculadasToAttach = em.getReference(entidadesVinculadasListEntidadesVinculadasToAttach.getClass(), entidadesVinculadasListEntidadesVinculadasToAttach.getEntidadesVinculadasPK());
                attachedEntidadesVinculadasList.add(entidadesVinculadasListEntidadesVinculadasToAttach);
            }
            proyecto.setEntidadesVinculadasList(attachedEntidadesVinculadasList);
            em.persist(proyecto);
            if (cedulaProfesor != null) {
                cedulaProfesor.getProyectoList().add(proyecto);
                cedulaProfesor = em.merge(cedulaProfesor);
            }
            if (facultad != null) {
                facultad.getProyectoList().add(proyecto);
                facultad = em.merge(facultad);
            }
            for (Archivos archivosListArchivos : proyecto.getArchivosList()) {
                Proyecto oldProyectoOfArchivosListArchivos = archivosListArchivos.getProyecto();
                archivosListArchivos.setProyecto(proyecto);
                archivosListArchivos = em.merge(archivosListArchivos);
                if (oldProyectoOfArchivosListArchivos != null) {
                    oldProyectoOfArchivosListArchivos.getArchivosList().remove(archivosListArchivos);
                    oldProyectoOfArchivosListArchivos = em.merge(oldProyectoOfArchivosListArchivos);
                }
            }
            for (Califica calificaListCalifica : proyecto.getCalificaList()) {
                Proyecto oldProyectoOfCalificaListCalifica = calificaListCalifica.getProyecto();
                calificaListCalifica.setProyecto(proyecto);
                calificaListCalifica = em.merge(calificaListCalifica);
                if (oldProyectoOfCalificaListCalifica != null) {
                    oldProyectoOfCalificaListCalifica.getCalificaList().remove(calificaListCalifica);
                    oldProyectoOfCalificaListCalifica = em.merge(oldProyectoOfCalificaListCalifica);
                }
            }
            for (EntidadesVinculadas entidadesVinculadasListEntidadesVinculadas : proyecto.getEntidadesVinculadasList()) {
                Proyecto oldProyectoOfEntidadesVinculadasListEntidadesVinculadas = entidadesVinculadasListEntidadesVinculadas.getProyecto();
                entidadesVinculadasListEntidadesVinculadas.setProyecto(proyecto);
                entidadesVinculadasListEntidadesVinculadas = em.merge(entidadesVinculadasListEntidadesVinculadas);
                if (oldProyectoOfEntidadesVinculadasListEntidadesVinculadas != null) {
                    oldProyectoOfEntidadesVinculadasListEntidadesVinculadas.getEntidadesVinculadasList().remove(entidadesVinculadasListEntidadesVinculadas);
                    oldProyectoOfEntidadesVinculadasListEntidadesVinculadas = em.merge(oldProyectoOfEntidadesVinculadasListEntidadesVinculadas);
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            if (findProyecto(proyecto.getIdProyecto()) != null) {
                throw new PreexistingEntityException("Proyecto " + proyecto + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Proyecto proyecto) throws IllegalOrphanException, NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Proyecto persistentProyecto = em.find(Proyecto.class, proyecto.getIdProyecto());
            Profesor cedulaProfesorOld = persistentProyecto.getCedulaProfesor();
            Profesor cedulaProfesorNew = proyecto.getCedulaProfesor();
            Facultad facultadOld = persistentProyecto.getFacultad();
            Facultad facultadNew = proyecto.getFacultad();
            List<Archivos> archivosListOld = persistentProyecto.getArchivosList();
            List<Archivos> archivosListNew = proyecto.getArchivosList();
            List<Califica> calificaListOld = persistentProyecto.getCalificaList();
            List<Califica> calificaListNew = proyecto.getCalificaList();
            List<EntidadesVinculadas> entidadesVinculadasListOld = persistentProyecto.getEntidadesVinculadasList();
            List<EntidadesVinculadas> entidadesVinculadasListNew = proyecto.getEntidadesVinculadasList();
            List<String> illegalOrphanMessages = null;
            for (Archivos archivosListOldArchivos : archivosListOld) {
                if (!archivosListNew.contains(archivosListOldArchivos)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Archivos " + archivosListOldArchivos + " since its proyecto field is not nullable.");
                }
            }
            for (Califica calificaListOldCalifica : calificaListOld) {
                if (!calificaListNew.contains(calificaListOldCalifica)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Califica " + calificaListOldCalifica + " since its proyecto field is not nullable.");
                }
            }
            for (EntidadesVinculadas entidadesVinculadasListOldEntidadesVinculadas : entidadesVinculadasListOld) {
                if (!entidadesVinculadasListNew.contains(entidadesVinculadasListOldEntidadesVinculadas)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain EntidadesVinculadas " + entidadesVinculadasListOldEntidadesVinculadas + " since its proyecto field is not nullable.");
                }
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            if (cedulaProfesorNew != null) {
                cedulaProfesorNew = em.getReference(cedulaProfesorNew.getClass(), cedulaProfesorNew.getCedula());
                proyecto.setCedulaProfesor(cedulaProfesorNew);
            }
            if (facultadNew != null) {
                facultadNew = em.getReference(facultadNew.getClass(), facultadNew.getNombre());
                proyecto.setFacultad(facultadNew);
            }
            List<Archivos> attachedArchivosListNew = new ArrayList<Archivos>();
            for (Archivos archivosListNewArchivosToAttach : archivosListNew) {
                archivosListNewArchivosToAttach = em.getReference(archivosListNewArchivosToAttach.getClass(), archivosListNewArchivosToAttach.getArchivosPK());
                attachedArchivosListNew.add(archivosListNewArchivosToAttach);
            }
            archivosListNew = attachedArchivosListNew;
            proyecto.setArchivosList(archivosListNew);
            List<Califica> attachedCalificaListNew = new ArrayList<Califica>();
            for (Califica calificaListNewCalificaToAttach : calificaListNew) {
                calificaListNewCalificaToAttach = em.getReference(calificaListNewCalificaToAttach.getClass(), calificaListNewCalificaToAttach.getCalificaPK());
                attachedCalificaListNew.add(calificaListNewCalificaToAttach);
            }
            calificaListNew = attachedCalificaListNew;
            proyecto.setCalificaList(calificaListNew);
            List<EntidadesVinculadas> attachedEntidadesVinculadasListNew = new ArrayList<EntidadesVinculadas>();
            for (EntidadesVinculadas entidadesVinculadasListNewEntidadesVinculadasToAttach : entidadesVinculadasListNew) {
                entidadesVinculadasListNewEntidadesVinculadasToAttach = em.getReference(entidadesVinculadasListNewEntidadesVinculadasToAttach.getClass(), entidadesVinculadasListNewEntidadesVinculadasToAttach.getEntidadesVinculadasPK());
                attachedEntidadesVinculadasListNew.add(entidadesVinculadasListNewEntidadesVinculadasToAttach);
            }
            entidadesVinculadasListNew = attachedEntidadesVinculadasListNew;
            proyecto.setEntidadesVinculadasList(entidadesVinculadasListNew);
            proyecto = em.merge(proyecto);
            if (cedulaProfesorOld != null && !cedulaProfesorOld.equals(cedulaProfesorNew)) {
                cedulaProfesorOld.getProyectoList().remove(proyecto);
                cedulaProfesorOld = em.merge(cedulaProfesorOld);
            }
            if (cedulaProfesorNew != null && !cedulaProfesorNew.equals(cedulaProfesorOld)) {
                cedulaProfesorNew.getProyectoList().add(proyecto);
                cedulaProfesorNew = em.merge(cedulaProfesorNew);
            }
            if (facultadOld != null && !facultadOld.equals(facultadNew)) {
                facultadOld.getProyectoList().remove(proyecto);
                facultadOld = em.merge(facultadOld);
            }
            if (facultadNew != null && !facultadNew.equals(facultadOld)) {
                facultadNew.getProyectoList().add(proyecto);
                facultadNew = em.merge(facultadNew);
            }
            for (Archivos archivosListNewArchivos : archivosListNew) {
                if (!archivosListOld.contains(archivosListNewArchivos)) {
                    Proyecto oldProyectoOfArchivosListNewArchivos = archivosListNewArchivos.getProyecto();
                    archivosListNewArchivos.setProyecto(proyecto);
                    archivosListNewArchivos = em.merge(archivosListNewArchivos);
                    if (oldProyectoOfArchivosListNewArchivos != null && !oldProyectoOfArchivosListNewArchivos.equals(proyecto)) {
                        oldProyectoOfArchivosListNewArchivos.getArchivosList().remove(archivosListNewArchivos);
                        oldProyectoOfArchivosListNewArchivos = em.merge(oldProyectoOfArchivosListNewArchivos);
                    }
                }
            }
            for (Califica calificaListNewCalifica : calificaListNew) {
                if (!calificaListOld.contains(calificaListNewCalifica)) {
                    Proyecto oldProyectoOfCalificaListNewCalifica = calificaListNewCalifica.getProyecto();
                    calificaListNewCalifica.setProyecto(proyecto);
                    calificaListNewCalifica = em.merge(calificaListNewCalifica);
                    if (oldProyectoOfCalificaListNewCalifica != null && !oldProyectoOfCalificaListNewCalifica.equals(proyecto)) {
                        oldProyectoOfCalificaListNewCalifica.getCalificaList().remove(calificaListNewCalifica);
                        oldProyectoOfCalificaListNewCalifica = em.merge(oldProyectoOfCalificaListNewCalifica);
                    }
                }
            }
            for (EntidadesVinculadas entidadesVinculadasListNewEntidadesVinculadas : entidadesVinculadasListNew) {
                if (!entidadesVinculadasListOld.contains(entidadesVinculadasListNewEntidadesVinculadas)) {
                    Proyecto oldProyectoOfEntidadesVinculadasListNewEntidadesVinculadas = entidadesVinculadasListNewEntidadesVinculadas.getProyecto();
                    entidadesVinculadasListNewEntidadesVinculadas.setProyecto(proyecto);
                    entidadesVinculadasListNewEntidadesVinculadas = em.merge(entidadesVinculadasListNewEntidadesVinculadas);
                    if (oldProyectoOfEntidadesVinculadasListNewEntidadesVinculadas != null && !oldProyectoOfEntidadesVinculadasListNewEntidadesVinculadas.equals(proyecto)) {
                        oldProyectoOfEntidadesVinculadasListNewEntidadesVinculadas.getEntidadesVinculadasList().remove(entidadesVinculadasListNewEntidadesVinculadas);
                        oldProyectoOfEntidadesVinculadasListNewEntidadesVinculadas = em.merge(oldProyectoOfEntidadesVinculadasListNewEntidadesVinculadas);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                String id = proyecto.getIdProyecto();
                if (findProyecto(id) == null) {
                    throw new NonexistentEntityException("The proyecto with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(String id) throws IllegalOrphanException, NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Proyecto proyecto;
            try {
                proyecto = em.getReference(Proyecto.class, id);
                proyecto.getIdProyecto();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The proyecto with id " + id + " no longer exists.", enfe);
            }
            List<String> illegalOrphanMessages = null;
            List<Archivos> archivosListOrphanCheck = proyecto.getArchivosList();
            for (Archivos archivosListOrphanCheckArchivos : archivosListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Proyecto (" + proyecto + ") cannot be destroyed since the Archivos " + archivosListOrphanCheckArchivos + " in its archivosList field has a non-nullable proyecto field.");
            }
            List<Califica> calificaListOrphanCheck = proyecto.getCalificaList();
            for (Califica calificaListOrphanCheckCalifica : calificaListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Proyecto (" + proyecto + ") cannot be destroyed since the Califica " + calificaListOrphanCheckCalifica + " in its calificaList field has a non-nullable proyecto field.");
            }
            List<EntidadesVinculadas> entidadesVinculadasListOrphanCheck = proyecto.getEntidadesVinculadasList();
            for (EntidadesVinculadas entidadesVinculadasListOrphanCheckEntidadesVinculadas : entidadesVinculadasListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Proyecto (" + proyecto + ") cannot be destroyed since the EntidadesVinculadas " + entidadesVinculadasListOrphanCheckEntidadesVinculadas + " in its entidadesVinculadasList field has a non-nullable proyecto field.");
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            Profesor cedulaProfesor = proyecto.getCedulaProfesor();
            if (cedulaProfesor != null) {
                cedulaProfesor.getProyectoList().remove(proyecto);
                cedulaProfesor = em.merge(cedulaProfesor);
            }
            Facultad facultad = proyecto.getFacultad();
            if (facultad != null) {
                facultad.getProyectoList().remove(proyecto);
                facultad = em.merge(facultad);
            }
            em.remove(proyecto);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Proyecto> findProyectoEntities() {
        return findProyectoEntities(true, -1, -1);
    }

    public List<Proyecto> findProyectoEntities(int maxResults, int firstResult) {
        return findProyectoEntities(false, maxResults, firstResult);
    }

    private List<Proyecto> findProyectoEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Proyecto.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Proyecto findProyecto(String id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Proyecto.class, id);
        } finally {
            em.close();
        }
    }

    public int getProyectoCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Proyecto> rt = cq.from(Proyecto.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    
}
